﻿//_______________________________________________________________________________________________________________________
// Copy Right (c) 2010, 2011 SapiensIT Consulting GmbH, all rights reserved
//_______________________________________________________________________________________________________________________
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT
// NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//_______________________________________________________________________________________________________________________
// PROJECT:     sapiens.at.SharePoint.LookupPicker (SharePoint 2010/V4)
//_______________________________________________________________________________________________________________________
// VERSION:     2.0
//_______________________________________________________________________________________________________________________
// DESCRIPTION: 
//_______________________________________________________________________________________________________________________
// LICENSE:     Different licens Types apply to different file types:
//               - Source code files are governed by the MICROSOFT PUBLIC LICENSE (Ms-PL)
//               - Binary files are governed by MSDN CODE GALLERY BINARY LICENSE
//               - Documentation files are governed by CREATIVE COMMONS ATTRIBUTION 3.0 LICENSE
//
//               The licenses can be found at the projects source location.
//               If you do not agree, don't use it!
// 
//_______________________________________________________________________________________________________________________
// Start SharePoint Branding, visit http://www.cliggin.com! Visit us on http://www.sapiens.at! Tell your friends! 
//_______________________________________________________________________________________________________________________
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.WebControls;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Res = Sapiens.at.SharePoint.Fields.Resources.Sapiens_at_SharePoint_LookupPicker;

namespace Sapiens.at.SharePoint.Fields
{
    /// <summary>
    /// Represents the control to configure a <see cref="LookupPickerField"/>.
    /// </summary>
    public class LookupPickerFieldEditor : UserControl, IFieldEditor
    {
        LookupPickerField _lookupPickerField = null;

        /// <summary>
        /// Dropdownlist that shows the available webs.
        /// </summary>
        protected DropDownList WebField = null;
        /// <summary>
        /// Dropdownlist that shows the available lists.
        /// </summary>
        protected DropDownList ListField = null;
        /// <summary>
        /// Dropdownlists that shows the fields available for the lookup field.
        /// </summary>
        protected DropDownList MainDisplayColumnField = null;
        /// <summary>
        /// Checkboxlist that shows the available fields. The user can check which fields can be additionally searched.
        /// </summary>
        protected CheckBoxList AdditionalSearchColumnsField = null;
        /// <summary>
        /// Checkboxlist that shows the available fields. The user can check which fields will be displayed in the search results table.
        /// </summary>
        protected CheckBoxList AdditionalDisplayColumnsField = null;
        /// <summary>
        /// Checkboxlist that shows the available contenttypes.
        /// </summary>
        protected CheckBoxList ContentTypes = null;
        /// <summary>
        /// Checkbox that indicates whether the lookupfield can contain multiple listitems.
        /// </summary>
        protected CheckBox AllowMultiValue = null;
        /// <summary>
        /// Checkbox that indicates whether the user can search in the dialog without a search string.
        /// </summary>
        protected CheckBox AllowShowAll = null;
        /// <summary>
        /// Dropdownlist showing all possible search scopes.
        /// </summary>
        protected DropDownList SearchScope = null;

        /// <summary>
        /// Grouping container for <see cref="SearchScope"/>.
        /// </summary>
        protected InputFormControl IFC_Scope = null;
        /// <summary>
        /// Grouping container for <see cref="ContentTypes"/>.
        /// </summary>
        protected InputFormControl IFC_LimitContentTypes = null;
        /// <summary>
        /// Grouping container for <see cref="AdditionalDisplayColumnsField"/>.
        /// </summary>
        protected InputFormControl IFC_AdditioanlDisplayFields = null;
        /// <summary>
        /// Grouping container for <see cref="AdditionalSearchColumnsField"/>.
        /// </summary>
        protected InputFormControl IFC_AdditioanlSearchFields = null;

        /// <summary>
        /// returns false.
        /// </summary>
        public bool DisplayAsNewSection
        {
            get { return false; }
        }

        /// <summary>
        /// Initializes the control with the data from a certain field.
        /// </summary>
        /// <param name="field"></param>
        public void InitializeWithField(SPField field)
        {
            _lookupPickerField = field as LookupPickerField;
            if (Page.IsPostBack) { return; }

            /*** Run first time initialization ***/
            // The drop down with webs in the current site 
            // collection is maintained with viewstate
            FillWebDropDown();
            
            // Get the selected list item for update scenario
            ListItem selectedWebListItem = null;
            if (_lookupPickerField != null && _lookupPickerField.LookupWebId != null)
            {
                selectedWebListItem = WebField.Items.FindByValue(_lookupPickerField.LookupWebId.ToString());
            }

            // If unavailable select the current web
            if (selectedWebListItem == null)
            {
                selectedWebListItem = WebField.Items.FindByValue(SPContext.Current.Web.ID.ToString());
            }
            selectedWebListItem.Selected = true;

            // Fill the list drop down for the current web,
            // it has an empty item on top in create scenarios
            FillListDropDown(selectedWebListItem.Value);

            // Get the selected list item for update scenario, 
            // do not default to first list in selected list
            ListItem selectedListListItem = null;
            if (_lookupPickerField != null && _lookupPickerField.LookupListId != null)
            {
                selectedListListItem = ListField.Items.FindByValue(_lookupPickerField.LookupListId.ToString());
            }
            if (selectedListListItem != null)
            {
                selectedListListItem.Selected = true;
                // Create the column list for update scenario
                Guid webID = new Guid(selectedWebListItem.Value);
                Guid listID = new Guid(selectedListListItem.Value);
                using (SPWeb web = SPContext.Current.Site.OpenWeb(webID))
                {
                    SPList list = web.Lists[listID];
                    FillMainDisplayColumnList(list);
                    FillAdditionalDisplayColumnsList(list);
                    FillContentTypes(list);

                    // Update the selected columns
                    string mainDisplayColumn = _lookupPickerField.LookupField;
                    string[] selectedSearchColumns = _lookupPickerField.AdditionalSearchFields;
                    string[] selectedDisplayColumns = _lookupPickerField.AdditionalDisplayFields;
                    ListItem mainDisplayColumnItem = MainDisplayColumnField.Items.FindByValue(mainDisplayColumn);
                    if (mainDisplayColumnItem != null)
                    {
                        mainDisplayColumnItem.Selected = true;
                    }
                    if (selectedSearchColumns != null && selectedSearchColumns.Length > 0)
                    {
                        foreach (string columnID in selectedSearchColumns)
                        {
                            ListItem columnListItem = AdditionalSearchColumnsField.Items.FindByValue(columnID);
                            // Column might have been deleted
                            if (columnListItem != null)
                            {
                                columnListItem.Selected = true;
                            }
                        }
                    }
                    if (selectedDisplayColumns != null && selectedDisplayColumns.Length > 0)
                    {
                        foreach (string columnID in selectedDisplayColumns)
                        {
                            ListItem columnListItem = AdditionalDisplayColumnsField.Items.FindByValue(columnID);
                            // Column might have been deleted
                            if (columnListItem != null)
                            {
                                columnListItem.Selected = true;
                            }
                        }
                    }
                    var contentTypes = LookupPickerData.GetContentTypes(list, _lookupPickerField.ContentTypes);
                    if (contentTypes != null && contentTypes.Length > 0)
                    {
                        foreach (var cType in contentTypes)
                        {
                            var ctypeListItem = ContentTypes.Items.FindByValue(cType.Id.ToString());
                            // Column might have been deleted
                            if (ctypeListItem != null)
                            {
                                ctypeListItem.Selected = true;
                            }
                        }
                    }
                    AllowMultiValue.Checked = _lookupPickerField != null ? _lookupPickerField.AllowMultipleValues : false;
                    AllowShowAll.Checked = _lookupPickerField != null ? _lookupPickerField.AllowShowAll : false;
                    var scopeListItem = SearchScope.Items.FindByValue(_lookupPickerField.SearchScope);
                    if (scopeListItem != null)
                    {
                        scopeListItem.Selected = true;
                    }
                }
            }
            if (field != null)
            {
                WebField.Enabled = false;
                ListField.Enabled = false;
            }
        }

        /// <summary>
        /// Sets some texts and fills the <see cref="SearchScope"/> dropdown.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            AllowShowAll.Text = Res.AllowShowAll;
            IFC_AdditioanlSearchFields.LabelText = Res.AdditionalSearchFields;
            IFC_AdditioanlDisplayFields.LabelText = Res.AdditionalDisplayFields;
            IFC_LimitContentTypes.LabelText = Res.LimitContentTypes;
            IFC_Scope.LabelText = Res.SearchScope;

            SearchScope.Items.Clear();
            SearchScope.Items.Add(new ListItem(Res.ScopeRecursiveAll, "RecursiveAll"));
            SearchScope.Items.Add(new ListItem(Res.ScopeNoFolders, "Recursive"));
            SearchScope.Items.Add(new ListItem(Res.ScopeRootLevelItems, ""));
            SearchScope.Items.Add(new ListItem(Res.ScopeFilesOnly, "FilesOnly"));     
        }

        /// <summary>
        /// Sets the values of the <see cref="LookupPickerField"/> according to the input of the user.
        /// </summary>
        /// <param name="field"></param>
        /// <param name="isNewField"></param>
        public void OnSaveChange(Microsoft.SharePoint.SPField field, bool isNewField)
        {
            LookupPickerField lookupPickerField = (LookupPickerField)field;
            if (isNewField)
            {
                lookupPickerField.LookupWebId = new Guid(WebField.SelectedValue);
                lookupPickerField.LookupList = ListField.SelectedValue;
            }
            lookupPickerField.LookupField = MainDisplayColumnField.SelectedValue;
            lookupPickerField.AdditionalSearchFields = AdditionalSearchColumnsField.Items.Cast<ListItem>().Where(li => li.Selected).Select(li => li.Value).ToArray();
            lookupPickerField.AdditionalDisplayFields = AdditionalDisplayColumnsField.Items.Cast<ListItem>().Where(li => li.Selected).Select(li => li.Value).ToArray();
            lookupPickerField.ContentTypes = ContentTypes.Items.Cast<ListItem>().Where(li => li.Selected).Select(li => li.Value).ToArray();
            lookupPickerField.AllowMultipleValues = AllowMultiValue.Checked;
            lookupPickerField.AllowShowAll = AllowShowAll.Checked;
            lookupPickerField.SearchScope = SearchScope.SelectedValue;
        }

        /// <summary>
        /// Change depending controls (List, Fields, ...).
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void WebField_SelectedIndexChanged(object sender, EventArgs e)
        {
            ListField.Items.Clear();
            MainDisplayColumnField.Items.Clear();
            AdditionalSearchColumnsField.Items.Clear();
            ContentTypes.Items.Clear();
            string selectedWebIDString = WebField.SelectedValue;
            if (String.IsNullOrEmpty(selectedWebIDString) == false)
            {
                FillListDropDown(selectedWebIDString);
            }
            Page.SetFocus(ListField);
        }

        /// <summary>
        /// Change depending controls (Fields)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void ListField_SelectedIndexChanged(object sender, EventArgs e)
        {
            AdditionalSearchColumnsField.Items.Clear();
            MainDisplayColumnField.Items.Clear();
            ContentTypes.Items.Clear();
            string selectedListIDString = ListField.SelectedValue;
            if (String.IsNullOrEmpty(selectedListIDString) == false)
            {
                using (SPWeb web = SPContext.Current.Site.OpenWeb(
                    new Guid(WebField.SelectedValue)))
                {
                    SPList list = web.Lists[new Guid(ListField.SelectedValue)];
                    FillMainDisplayColumnList(list);
                    FillAdditionalDisplayColumnsList(list);
                    FillContentTypes(list);
                }
            }
            //LinkToRelatedRecordField.Enabled = String.IsNullOrEmpty(selectedListIDString) == false;
            Page.SetFocus(MainDisplayColumnField);
        }

        void FillWebDropDown()
        {
            WebField.Items.Add("");
            SPSite site = SPContext.Current.Site;
            foreach (SPWeb web in site.AllWebs)
            {
                using (web)
                {
                    ListItem webListItem = new ListItem();
                    webListItem.Text = web.Title;
                    webListItem.Value = web.ID.ToString();
                    WebField.Items.Add(webListItem);
                }
            }
        }

        void FillListDropDown(string webIDString)
        {
            ListField.Items.Add("");
            Guid webID = new Guid(webIDString);
            using (SPWeb web = SPContext.Current.Site.OpenWeb(webID))
            {
                foreach (SPList list in web.Lists)
                {
                    if (list.Hidden == false)
                    {
                        ListItem listListItem = new ListItem();
                        listListItem.Text = list.Title;
                        listListItem.Value = list.ID.ToString();
                        ListField.Items.Add(listListItem);
                    }
                }
            }
        }

        void FillMainDisplayColumnList(SPList list)
        {
            FillColumnList(list, MainDisplayColumnField.Items);
        }

        void FillAdditionalDisplayColumnsList(SPList list)
        {
            FillColumnList(list, AdditionalSearchColumnsField.Items);
            FillColumnList(list, AdditionalDisplayColumnsField.Items);
        }

        void FillContentTypes(SPList list)
        {
            foreach (SPContentType cType in list.ContentTypes)
            {
                ContentTypes.Items.Add(new ListItem(cType.Name, cType.Id.ToString()));
            }
        }

        void FillColumnList(SPList spList, ListItemCollection list)
        {
            foreach (SPField field in GetDisplayColumns(spList))
            {
                string title = String.Concat(
                    field.Title, " ", field.AuthoringInfo);
                ListItem listItem = new ListItem(title);
                listItem.Value = field.InternalName;
                list.Add(listItem);
            }
        }

        IEnumerable<SPField> GetDisplayColumns(SPList list)
        {
            foreach (SPField field in list.Fields)
            {
                if (field.Hidden == false)
                {
                    switch (field.Type)
                    {
                        case SPFieldType.Calculated:
                            if (((SPFieldCalculated)field).OutputType == SPFieldType.Text)
                            {
                                yield return field;
                            }
                            break;
                        case SPFieldType.Computed:
                            if (((SPFieldComputed)field).EnableLookup)
                            {
                                yield return field;
                            }
                            break;
                        case SPFieldType.Counter:
                        case SPFieldType.Text:
                            yield return field;
                            break;
                    }
                }
            }
        }
    }
}
